import { subscribeWithSelector } from 'zustand/middleware'
import create from 'zustand'
import { isMatch } from '@/pages/manager/utils/utils'
import { differenceBy, uniqBy } from 'lodash-es'
import { listToggle } from '@/utils/listSlice'
import { SimpleUserModel, UserModel } from '../../blocks/user/interface'
import { UserEntity } from '@/api/create/interface'
import { useUserInteractiveStore } from '../../blocks/user/interactive/store'
import { useUserOftenStore } from '../../blocks/user/often/store'
import { useUserAllStore } from '../../blocks/user/all/store'
import { useBasicInfoStore } from '../../blocks/basicInfo/store'
/**选中的元素 */
export interface SelectedModel {
	mcc: UserEntity
	status: {
		checked: boolean
	}
	uuid: string
}
type Chosen = {
	_prevClickSelectItem: { start: string; prevChosen: string[] } | null
	chosenMap: { [mtKey: string]: boolean }
}
type StateStore = {
	list: UserModel[]
	tab: 'all' | 'often' | 'interactive'
	all: {
		openMap: { [mtKey: string]: boolean }
	} & Chosen
	often: Chosen
	interactive: Chosen
	selectedList: SelectedModel[]
	_start: string | null
	_changes: string[]
	/**搜索文本 */
	searchVal: string
}
type IStore = StateStore & {
	update: (d: Partial<StateStore>) => void
	reset: () => void
	itemHandle: (mtKey: string, type: 'click' | 'ctrl' | 'shift') => void
	/**全部终端 */
	getListFromTableAll: (tree: UserModel[], keywords: string) => void
	/**常用终端*/
	getListFromTableOften: (tree: SimpleUserModel[], keywords: string) => void
	/**互动终端*/
	getListFromTableInteractive: (list: SimpleUserModel[], keywords: string) => void
	getListFromTable: (tree: UserModel[], keywords: string) => void
	/**选中dom*/
	clickSelectItem: (
		data: UserEntity,
		{ ctrlKey, shiftKey }: { ctrlKey: boolean; shiftKey: boolean },
		uuid: string
	) => void
	itemAddToRight: (data: UserEntity, uuid: string) => void
	clearChosen: () => void
	addAllToRight: () => void
	addAllSelectedToRight: () => void
	removeSelectedItem: (mtKey: string) => void
	/**移除选中的终端*/
	removeSelectedCheckedItem: () => void
	removeAllSelectedItem: () => void
	mtChange2SelectedItem: () => void
	/**平铺树结构 不更具当前的uuid节点是否展开了 */
	flatAllTreeToListNoOpenMap: (tree: UserModel[]) => UserModel[]
	/**平铺树 */
	flatAllTreeToList: (tree: UserModel[]) => UserModel[]
	/**从树里面获取对应的uuid的终端*/
	getMtModel: (d: Array<string>) => Array<SelectedModel>
}
const initialState: StateStore = {
	list: [],
	tab: 'all',
	all: { _prevClickSelectItem: null, chosenMap: {}, openMap: {} },
	often: { _prevClickSelectItem: null, chosenMap: {} },
	interactive: { _prevClickSelectItem: null, chosenMap: {} },
	selectedList: [],
	_start: null,
	_changes: [],
	searchVal: '',
}

export const useSinglePollStore = create<IStore>()(
	subscribeWithSelector((set, get, api) => ({
		...initialState,
		update: (d) => set({ ...d }),
		reset: () => set(initialState),
		_tree: () => {},
		flatAllTreeToListNoOpenMap: (tree: UserModel[]) => {
			let stack = [...tree]
			let result = []
			while (stack.length !== 0) {
				const item = stack.shift()!
				result.push({
					mcc: item.mcc,
					status: item.status,
					attr: item.attr,
					uuid: item.uuid,
					parentId: item.parentId,
					nestingLevel: item.nestingLevel,
					children: [],
				})
				if (item.mcc.account_type === 10 && !item.attr.isSimpleCascade) {
					for (let i = item.children.length - 1; i >= 0; i--) {
						let o = item.children[i]
						stack.unshift({
							mcc: o.mcc,
							status: o.status,
							attr: o.attr,
							uuid: o.uuid,
							parentId: o.parentId,
							children: o.children,
							nestingLevel: item.nestingLevel + 1,
						})
					}
				}
			}
			return result
		},
		flatAllTreeToList: (tree: UserModel[]) => {
			let stack = [...tree]
			let result = []
			const openMap = useSinglePollStore.getState().all.openMap
			while (stack.length !== 0) {
				const item = stack.shift()!
				const superMtNum = useBasicInfoStore.getState().superMtNum
				/**此处需要过滤会议终端*/
				if (!superMtNum && item.mcc.account_type === 10 && !item.attr.isSimpleCascade) {
					/**非超大方非级联会议不需要参与筛选*/
					result.push({
						mcc: item.mcc,
						status: item.status,
						attr: item.attr,
						uuid: item.uuid,
						parentId: item.parentId,
						nestingLevel: item.nestingLevel,
						children: [],
					})
				} else {
					let isMatchSearch = isMatch(item.mcc, get().searchVal)
					if (isMatchSearch) {
						result.push({
							mcc: item.mcc,
							status: item.status,
							attr: item.attr,
							uuid: item.uuid,
							parentId: item.parentId,
							nestingLevel: item.nestingLevel,
							children: [],
						})
					}
				}
				/**非超大方非级联会议不需要参与筛选  判断是否需要展开  如果需要就展开否则不需要遍历*/
				if (item.mcc.account_type === 10 && !item.attr.isSimpleCascade && openMap[item.uuid]) {
					for (let i = item.children.length - 1; i >= 0; i--) {
						let o = item.children[i]
						stack.unshift({
							mcc: o.mcc,
							status: o.status,
							attr: o.attr,
							uuid: o.uuid,
							parentId: o.parentId,
							children: o.children,
							nestingLevel: item.nestingLevel + 1,
						})
					}
				}
			}
			return result
		},

		getListFromTableAll: (tree, keywords) => {
			const { flatAllTreeToList } = get()
			set({ list: flatAllTreeToList(tree) })
		},
		getListFromTableOften: (tree, keywords) => {
			let result = []
			for (let i = 0; i < tree.length; i++) {
				const item = tree[i]
				let isMatchSearch = isMatch(item.mcc, keywords)
				if (isMatchSearch) {
					result.push({
						mcc: item.mcc,
						nestingLevel: 0,
						children: [],
						uuid: item.uuid,
						parentId: item.parentId,
						status: {
							checked: false,
							isOpen: false,
							isMatchSearch: false,
							isOften: false,
							isInteractive: false,
						},
						attr: {
							actualUuid: item.uuid,
							isSimpleCascade: false,
						},
					})
				}
			}
			set({ list: result })
		},
		getListFromTableInteractive: (tree, keywords) => {
			let result = []
			for (let i = 0; i < tree.length; i++) {
				const item = tree[i]
				let isMatchSearch = isMatch(item.mcc, keywords)
				if (isMatchSearch) {
					result.push({
						mcc: item.mcc,
						nestingLevel: 0,
						children: [],
						uuid: item.uuid,
						parentId: item.parentId,
						status: {
							checked: false,
							isOpen: false,
							isMatchSearch: false,
							isOften: false,
							isInteractive: false,
						},
						attr: {
							actualUuid: item.uuid,
							isSimpleCascade: false,
						},
					})
				}
			}
			set({ list: result })
		},
		getListFromTable(list, keywords) {},
		clickSelectItem: (data, { ctrlKey, shiftKey }, uuid) => {
			const { tab, list } = get()
			let prevClickSelectItem = get()[tab]._prevClickSelectItem
			let chosenMap = get()[tab].chosenMap
			if (shiftKey) {
				if (prevClickSelectItem) {
					const { start, prevChosen } = prevClickSelectItem
					if (prevChosen.length > 0) {
						//说明已经有过一次shift操作，需要把这次操作结果复原
						for (const item of list) {
							if (prevChosen.includes(item.uuid)) {
								chosenMap[item.uuid] = false
							}
						}
					}
					const startItem = list.find((x) => x.uuid === start)
					let newChosen = []
					if (!startItem || startItem.uuid === uuid) {
						//比如经过搜索，初始值没了，那就重新记录;或者初始值和当前值一样
						chosenMap[uuid] = true
						prevClickSelectItem.start = uuid
					} else {
						let _flag = false,
							_time = 0
						for (const item of list) {
							const superMtNum = useBasicInfoStore.getState().superMtNum
							/**此处需要过滤会议终端*/
							if (!superMtNum && item.mcc.account_type === 10 && !item.attr.isSimpleCascade) continue
							if (item.uuid === uuid || item.uuid === start) {
								chosenMap[item.uuid] = true
								newChosen.push(item.uuid)
								_flag = ++_time === 1
							}
							if (_flag) {
								chosenMap[item.uuid] = true
								newChosen.push(item.uuid)
							}
						}
					}
					prevClickSelectItem.prevChosen = newChosen
				} else {
					chosenMap[uuid] = true
					prevClickSelectItem = { start: uuid, prevChosen: [] }
				}
			} else {
				if (ctrlKey) {
					chosenMap[uuid] = !chosenMap[uuid]
				} else {
					chosenMap = {
						[uuid]: true,
					}
				}
				prevClickSelectItem = { start: uuid, prevChosen: [] }
			}
			set((s) => ({
				...s,
				[tab]: { ...s[tab], chosenMap: { ...chosenMap }, _prevClickSelectItem: prevClickSelectItem },
			}))
		},
		clearChosen: () => {
			set((s) => ({
				...s,
				all: { ...s.all, _prevClickSelectItem: null, chosenMap: {} },
				often: { _prevClickSelectItem: null, chosenMap: {} },
				interactive: { _prevClickSelectItem: null, chosenMap: {} },
			}))
		},
		itemAddToRight: (data, uuid) => {
			/**获取选中的数据 */
			const selectedList = get().selectedList
			/**遍历去重*/
			for (let i = 0; i < selectedList.length; i++) {
				if (selectedList[i].uuid === uuid) return
			}
			/**添加数据*/
			selectedList.push({
				mcc: data,
				uuid: uuid,
				status: {
					checked: false,
				},
			})
			set({ selectedList: [...selectedList] })
			get().clearChosen()
		},
		addAllToRight: () => {
			//todo 应该和添加与会方保持一致，后面再改
			const selectedList = get().selectedList
			const { tab, list } = get()
			if (tab === 'often' || tab === 'interactive') {
				const insertList = differenceBy(list, selectedList, (x) => x.uuid)
				let _result = insertList.map(
					(x) =>
						({
							mcc: x.mcc,
							uuid: x.uuid,
							status: {
								checked: false,
							},
						} as SelectedModel)
				)
				let result = uniqBy(_result, 'uuid')
				set({ selectedList: [...selectedList, ...result] })
			}
			if (tab === 'all') {
				/**不能加入会议终端*/
				const insertList = differenceBy(list, selectedList, (x) => x.uuid).filter((item) => {
					return (item.mcc.account_type === 10 && item.attr.isSimpleCascade) || item.mcc.account_type !== 10
				})
				let _result = insertList.map(
					(x) =>
						({
							mcc: x.mcc,
							uuid: x.uuid,
							status: {
								checked: false,
							},
						} as SelectedModel)
				)
				let result = uniqBy(_result, 'uuid')
				set({ selectedList: [...selectedList, ...result] })
			}
		},
		/**从树里面获取对应的uuid的终端*/
		getMtModel: (insertMtKeys) => {
			const { flatAllTreeToListNoOpenMap, tab } = get()
			const tree = useUserAllStore.getState().tree
			let result = flatAllTreeToListNoOpenMap(tree)
			let filter_list = result
				.filter((item) => {
					return insertMtKeys.includes(item.uuid)
				})
				.filter((item, index, self) => index === self.findIndex((j) => j.uuid === item.uuid)) //去重

			return filter_list.map((x) => {
				return {
					mcc: x.mcc,
					uuid: x.uuid,
					status: {
						checked: false,
					},
				}
			})
		},
		addAllSelectedToRight: () => {
			const { tab, selectedList, getMtModel } = get()
			const chosenMap = get()[tab].chosenMap
			let mtKeys = []
			for (const mtKey in chosenMap) {
				if (chosenMap[mtKey]) {
					mtKeys.push({ uuid: mtKey })
				}
			} //去重
			const insertMtKeys = differenceBy(mtKeys, selectedList, (x) => x.uuid).map((x) => x.uuid)
			let result: SelectedModel[] = []
			if (tab === 'all') {
				result = getMtModel(insertMtKeys)
			} else if (tab === 'often') {
				const _oftenList = useUserOftenStore.getState().list
				const _result = _oftenList
					.filter((x) => insertMtKeys.includes(x.uuid))
					.map(
						(x) =>
							({
								mcc: x.mcc,
								uuid: x.uuid,
								status: {
									checked: false,
								},
							} as SelectedModel)
					)
				result = uniqBy(_result, 'uuid')
			} else if (tab === 'interactive') {
				const _interactiveList = useUserInteractiveStore.getState().list
				const _result = _interactiveList
					.filter((x) => insertMtKeys.includes(x.uuid))
					.map(
						(x) =>
							({
								mcc: x.mcc,
								uuid: x.uuid,
								status: {
									checked: false,
								},
							} as SelectedModel)
					)
				result = uniqBy(_result, 'uuid')
			}
			set({ selectedList: [...selectedList, ...result] })
		},
		removeSelectedItem: (uuid) => {
			const selectedList = get().selectedList
			let s = selectedList.filter((x) => x.uuid !== uuid)
			set({ selectedList: s })
		},
		removeSelectedCheckedItem: () => {
			const selectedList = get().selectedList
			let s = selectedList.filter((x) => !x.status.checked)
			set({ selectedList: s })
		},
		removeAllSelectedItem: () => {
			set({ selectedList: [] })
		},
		mtChange2SelectedItem: () => {
			// let selectedList = get().selectedList
			// let mtKeys = selectedList.map((x) => x.mtKey)
			// const getMtModel = useTableAllStore.getState().getMtModel
			// let mtModels = getMtModel(mtKeys)
			// for (let i = 0; i < selectedList.length; i++) {
			// 	const s = selectedList[i]
			// 	if (mtModels[i]) {
			// 		s.mcc = mtModels[i]!.mcc as Mt
			// 	}
			// }
			// set({ selectedList: [...selectedList] })
		},
		itemHandle: (mtKey, type) => {
			const { selectedList, _start, _changes } = get()
			const result = listToggle<SelectedModel, 'uuid'>(
				selectedList,
				{
					_start,
					_changes,
					action: type,
					path: 'uuid',
				},
				mtKey
			)
			set({ selectedList: result.list, _start: result._start, _changes: result._changes })
		},
	}))
)
